package com.qrback.service.impl;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.qrback.entity.Device;
import com.qrback.entity.OperationLog;
import com.qrback.entity.User;
import com.qrback.repository.DeviceRepository;
import com.qrback.repository.OperationLogRepository;
import com.qrback.repository.UserRepository;
import com.qrback.service.DeviceService;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class DeviceServiceImpl implements DeviceService {
    
    @Autowired
    private DeviceRepository deviceRepository;
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private OperationLogRepository operationLogRepository;
    
    @Value("${qr.code.storage.path}")
    private String qrCodeStoragePath;
    
    @Override
    public List<Device> getAllDevices() {
        return deviceRepository.findAll();
    }
    
    @Override
    public Device getDeviceById(Integer id) {
        return deviceRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("设备不存在"));
    }
    
    @Override
    public Device getDeviceByDeviceCode(String deviceCode) {
        return deviceRepository.findByDeviceCode(deviceCode)
                .orElseThrow(() -> new RuntimeException("设备不存在"));
    }
    
    @Override
    public Device createDevice(Device device, Integer userId) {
        // 验证deviceCode不为null
        if (device.getDeviceCode() == null || device.getDeviceCode().trim().isEmpty()) {
            throw new RuntimeException("设备编号不能为空");
        }
        
        // 检查设备编号是否已存在
        if (deviceRepository.existsByDeviceCode(device.getDeviceCode())) {
            throw new RuntimeException("设备编号已存在");
        }
        
        // 设置创建者
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        device.setCreatedBy(user);
        
        // 确保必填字段都不为null
        if (device.getDeviceName() == null) {
            device.setDeviceName("");
        }
        if (device.getDeviceType() == null) {
            device.setDeviceType("");
        }
        if (device.getDescription() == null) {
            device.setDescription("");
        }
        
        // 保存设备
        Device savedDevice = deviceRepository.save(device);
        
        // 记录操作日志
        logOperation(user, savedDevice, "create", "创建设备：" + device.getDeviceName());
        
        // 生成二维码
        generateDeviceQrCode(savedDevice.getId());
        
        return savedDevice;
    }
    
    @Override
    public Device updateDevice(Device device) {
        Device existingDevice = deviceRepository.findById(device.getId())
                .orElseThrow(() -> new RuntimeException("设备不存在"));
        
        // 更新设备信息
        existingDevice.setDeviceName(device.getDeviceName());
        existingDevice.setProductionDate(device.getProductionDate());
        existingDevice.setDeviceType(device.getDeviceType());
        existingDevice.setDescription(device.getDescription());
        
        // 如果设备编号变更，检查是否已存在
        if (device.getDeviceCode() != null && !device.getDeviceCode().equals(existingDevice.getDeviceCode())) {
            if (deviceRepository.existsByDeviceCode(device.getDeviceCode())) {
                throw new RuntimeException("设备编号已存在");
            }
            existingDevice.setDeviceCode(device.getDeviceCode());
        }
        
        // 保存更新后的设备
        Device updatedDevice = deviceRepository.save(existingDevice);
        
        // 记录操作日志
        logOperation(updatedDevice.getCreatedBy(), updatedDevice, "update", "更新设备：" + device.getDeviceName());
        
        return updatedDevice;
    }
    
    @Override
    public void deleteDevice(Integer id) {
        Device device = deviceRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("设备不存在"));
        
        // 删除二维码文件（如果存在）
        if (device.getQrcodeUrl() != null) {
            try {
                File file = new File(device.getQrcodeUrl());
                if (file.exists()) {
                    file.delete();
                }
            } catch (Exception e) {
                // 记录错误但不阻止删除设备
                e.printStackTrace();
            }
        }
        
        // 记录操作日志
        logOperation(device.getCreatedBy(), device, "delete", "删除设备：" + device.getDeviceName());
        
        // 删除设备
        deviceRepository.delete(device);
    }
    
    @Override
    public List<Device> filterDevices(Map<String, Object> filters) {
        // 这里简化实现，实际项目中需要根据filters参数构建查询条件
        return deviceRepository.findAll();
    }
    
    @Override
    public List<Device> getDevicesByType(String deviceType) {
        return deviceRepository.findByDeviceType(deviceType);
    }
    
    @Override
    public List<Device> getDevicesByProductionDateRange(Date startDate, Date endDate) {
        return deviceRepository.findByProductionDateBetween(startDate, endDate);
    }
    
    @Override
    public String generateDeviceQrCode(Integer deviceId) {
        Device device = deviceRepository.findById(deviceId)
                .orElseThrow(() -> new RuntimeException("设备不存在"));
        
        try {
            // 确保存储目录存在
            File directory = new File(qrCodeStoragePath);
            if (!directory.exists()) {
                directory.mkdirs();
            }
            
            // 二维码内容：设备详情URL或设备ID
            String content = "device_id:" + device.getId();
            
            // 二维码图片路径
            String filename = "device_" + device.getId() + ".png";
            String filePath = qrCodeStoragePath + filename;
            
            // 设置二维码参数
            Map<EncodeHintType, Object> hints = new HashMap<>();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            hints.put(EncodeHintType.MARGIN, 2);
            
            // 生成二维码
            BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, 300, 300, hints);
            
            // 输出到文件
            Path path = Paths.get(filePath);
            MatrixToImageWriter.writeToPath(bitMatrix, "png", path);
            
            // 更新设备的二维码路径
            device.setQrcodeUrl(filePath);
            deviceRepository.save(device);
            
            return filePath;
        } catch (Exception e) {
            throw new RuntimeException("生成二维码失败", e);
        }
    }
    

    
    @Override
    public void exportDevicesToExcel(OutputStream outputStream, List<Device> devices) {
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("设备信息");
        
        // 创建表头
        Row headerRow = sheet.createRow(0);
        String[] headers = {"设备名称", "生产日期", "设备类型", "设备编号", "描述", "创建时间"};
        for (int i = 0; i < headers.length; i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers[i]);
        }
        
        // 调用通用的填充数据方法
        fillExcelWithDevices(workbook, sheet, headers, devices);
        
        try {
            // 写入输出流
            workbook.write(outputStream);
            workbook.close();
        } catch (Exception e) {
            throw new RuntimeException("导出Excel失败", e);
        }
    }
    
    // 通用的填充Excel数据方法
    private void fillExcelWithDevices(Workbook workbook, Sheet sheet, String[] headers, List<Device> devices) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        int rowNum = 1;
        for (Device device : devices) {
            Row row = sheet.createRow(rowNum++);
            row.createCell(0).setCellValue(device.getDeviceName());
            
            if (device.getProductionDate() != null) {
                row.createCell(1).setCellValue(dateFormat.format(device.getProductionDate()));
            }
            
            row.createCell(2).setCellValue(device.getDeviceType());
            row.createCell(3).setCellValue(device.getDeviceCode());
            row.createCell(4).setCellValue(device.getDescription() != null ? device.getDescription() : "");
            row.createCell(5).setCellValue(dateFormat.format(device.getCreatedAt()));
        }
        
        // 自动调整列宽
        for (int i = 0; i < headers.length; i++) {
            sheet.autoSizeColumn(i);
        }
    }
    
    @Override
    public boolean existsByDeviceCode(String deviceCode) {
        return deviceRepository.existsByDeviceCode(deviceCode);
    }
    
    // 记录操作日志
    private void logOperation(User user, Device device, String operation, String details) {
        OperationLog log = new OperationLog();
        log.setUser(user);
        log.setDevice(device);
        log.setOperation(operation);
        log.setDetails(details);
        operationLogRepository.save(log);
    }
}